﻿#ifndef CABINETMANAGER_H_
#define CABINETMANAGER_H_

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>

#include <QObject>
#include <QMutex>
#include <QUdpSocket>

#include "CommonType.h"
#include "zlbase/controllor/IDoorControlBoard.h"

#define ZL_AVAILABEL_MASK (ELockerStatus_Error | ELockerStatus_Expired | ELockerStatus_Occupied | ELockerStatus_Item | ELockerStatus_Locked)

using namespace std;

namespace zl {

// cabinet manager
class CCabinetManager : public QObject
{
	Q_OBJECT
public:
	static CCabinetManager* Instance();
	static void Release();

    // 初始化基础中间件配置信息
    inline void InitZLBaseConfig(const zl::ZLBaseConfig& cfg) {
        create_door_control_board_devices(cfg.dcb_list);
    }
    int32_t ResetZLBaseConfig(const zl::ZLBaseConfig& cfg);

    // 格口分配/管理
    inline void LoadCabinetData() { load_locker_status_data(); }
	int32_t SetLockerStatus(int32_t boxno, ELockerStatus index, bool flag);
	int32_t GetLockerStatus(int32_t boxno);
	int32_t GetAllLockers(LockerVec& vec);
    // 根据类型获取格口对象，mask表示过滤条件，即mask中被设置的状态位，也在格口的状态位中被设置了
    // 则过滤掉该格口
    int32_t GetLockersByType(LockerVec& vec, ELockerType type, int32_t mask = 0x00);
    int32_t GetAvilableLocker(ELockerType type = ELockerType_Default, int32_t mask = ZL_AVAILABEL_MASK);

    // 格口控制
	int32_t OpenBox(int32_t boxno);
	int32_t OpenAll();
	int32_t CleanBox(int32_t boxno);
	int32_t CleanAll();
	int32_t LockBox(int32_t boxno);
	int32_t UnlockBox(int32_t boxno);

    // 管理卡模块
	int32_t RegisterManagerCard(const std::string& cardno);
	int32_t VerifyManagerCard(const std::string& cardno);
	int32_t UpdateManagerCardStatus(const std::string& cardno, int32_t status);
	int32_t DeleteManagerCard(const std::string& cardno);
	int32_t GetManagerCardList(ManagerCardVec& vec);

protected:
	explicit CCabinetManager(QObject* parent = 0);
	~CCabinetManager();

	void load_locker_status_data();
	int32_t save_locker_status_data();
    void clean_locker_status_data();
	void update_locker_status(ELockerStatus flag, int32_t pcbno, unsigned char* buf, int32_t len);
    int32_t calc_locker_status(int32_t status, ELockerStatus index, bool flag);

	Locker get_locker(int32_t boxno);
    void create_door_control_board_devices(const std::vector<DoorControlBoard>& dcb_list);
    int32_t convert_layout_typestr(char typestr);
    void start_work_thread();

	void timerEvent(QTimerEvent *event) override;	

signals:
    void lockerStatusChanged(int boxno);

private:
	static CCabinetManager*	instance_;

    std::mutex          mutex_lockers_;
    LockerVec			lockers_;
    std::thread*        work_thread_;
    bool                work_flag_;
    std::mutex          mutex_device_;
    std::vector<std::shared_ptr<zlbase::IDoorControlBoard>> device_list_;
};

}

#endif // CABINETMANAGER_H_
